package com.nsi.service.Impl;

import com.aliyun.oos.demo.AliyunOSSClientUtil;
import com.aliyun.oos.demo.OSSClientConstants;
import com.aliyun.oss.OSSClient;
import com.nsi.common.ResponseCode;
import com.nsi.exception.NsiOperationException;
import com.nsi.service.IFileService;
import com.nsi.util.PropertiesUtil;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.RandomUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Luo Zhen
 */
@Service
@Slf4j
public class FileServiceImpl implements IFileService {

    // 统一所有文件后缀上传格式
    private static final String FILE_SUFFIX = ".png";

    /**
     * 文化上传
     *
     * @param userMail
     * @param userTrueName
     * @return
     */
    @Override
    public String upFile(MultipartFile file, String userMail, String userTrueName, String path) {
        String fileName = file.getOriginalFilename();
        //拼接后的新名字
        String uploadFile = userMail + userTrueName + FILE_SUFFIX;
        log.info("【上传文件】,上传文件名:{},上传路径:{},新文件名:{}", fileName, path, uploadFile);

        File fileDir = new File(path);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        File targetFile = new File(path, uploadFile);
        try {
            //开始上传
            file.transferTo(targetFile);
        } catch (IOException e) {
            log.info("上传失败", e);
            e.printStackTrace();
        }
        return targetFile.getName();
    }

    @Override
    public String uploadResume(MultipartFile file, String type, String newFileName) {
        return UploadOOSFile(file, type, newFileName);
    }

    /**
     * 图片上传
     *
     * @param file
     * @return
     */
    @Override
    public String upload(MultipartFile file, String type) {
        String fileName = file.getOriginalFilename();
        if (this.verifyImgSuffixes(fileName)) return "";
        //拼接后的新名字
        String uploadFile = System.currentTimeMillis() + FILE_SUFFIX;
        return UploadOOSFile(file, type, uploadFile);
    }


    /**
     * 上传学校库logo
     *
     * @param file
     * @param type
     * @return
     */
    @Override
    public String uploadSchoolLogo(MultipartFile file, String type, Integer schoolId) {
        String fileName = file.getOriginalFilename();
        if (this.verifyImgSuffixes(fileName)) return "";
        //拼接名字
        String uploadFile = schoolId + "-logo" + FILE_SUFFIX;
        return UploadOOSFile(file, type, uploadFile);
    }

    /**
     * 验证文件后缀是否规范
     *
     * @param fileName
     * @return
     */
    private boolean verifyImgSuffixes(String fileName) {
        String fileExtensionName = fileName.substring(fileName.lastIndexOf(".") + 1);
        if (!fileExtensionName.equalsIgnoreCase("JPG")
                && !fileExtensionName.equalsIgnoreCase("PNG")
                && !fileExtensionName.equalsIgnoreCase("JPEG")) {
            return true;
        }
        return false;
    }

    @Override
    public String uploadSchoolBigImage(MultipartFile file, String type, Integer schoolId) {
        String fileName = file.getOriginalFilename();
        if (this.verifyImgSuffixes(fileName)) return "";
        //拼接后的新名字
        String uploadFile = schoolId + "-show" + RandomUtils.nextInt(1000, 9999) + FILE_SUFFIX;
        return UploadOOSFile(file, type, uploadFile);
    }

    /**
     * 公共上传OSS图片
     *
     * @param file        图片
     * @param type        文件路径
     * @param newFileName 新文件名字
     * @return
     */
    private String UploadOOSFile(MultipartFile file, String type, String newFileName) {
        String path = "C:" + File.separator + "upImage" + File.separator + "nsi-class" + File.separator;
        log.info("【文件上传】上传路径:{},新文件名:{}", path, newFileName);
        File fileDir = new File(path);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        File targetFile = new File(path, newFileName);
        try {
            //开始上传本地
            file.transferTo(targetFile);
            OSSClient ossClient = AliyunOSSClientUtil.getOSSClient();
            AliyunOSSClientUtil.uploadObject2OSS(ossClient, targetFile, OSSClientConstants.BACKET_NAME, type);
            log.info("【文件上传】上传OOS成功!!!");
            //删除本地文件
            targetFile.delete();

        } catch (Exception e) {
            log.error("【文件上传】上传失败", e);
            throw new NsiOperationException(ResponseCode.UPLOAD_ERROR);
        }
        return targetFile.getName();
    }

    /**
     * base64 图片上传
     *
     * @param strImage
     * @param type
     * @return
     */
    @Override
    public String base64Upload(String strImage, String type) {
        String fileName = System.currentTimeMillis() + FILE_SUFFIX;
        String path = PropertiesUtil.getProperty("article.html.url");
        FileServiceImpl.generateImage(strImage, path + fileName);
        File targetFile = new File(path, fileName);
        OSSClient ossClient = AliyunOSSClientUtil.getOSSClient();
        AliyunOSSClientUtil.uploadObject2OSS(ossClient, targetFile, OSSClientConstants.BACKET_NAME, type);
        log.info("上传OOS成功!!!");
        //删除本地文件
        targetFile.delete();
        return targetFile.getName();
    }

    @Override
    public Map<String, String> base64Upload(String strImage, Integer schoolId) {
        Map<String, String> modelMap = new HashMap<>();
        String fileName = schoolId + ".jpg";
        String path = "C:" + File.separator + "upImage" + File.separator + "upSchoolImg" + File.separator + "school_logo" + File.separator;
        File fileDir = new File(path);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        FileServiceImpl.generateImage(strImage, path + fileName);
        log.info("base64 写入本地成功");

        path = "/upImage/upSchoolImg/school_logo/" + fileName;
        modelMap.put("uri", fileName);
        modelMap.put("url", path);
        return modelMap;
    }

    /**
     * Base64传文件
     *
     * @param strImage
     * @param imgFilePath
     * @return
     */
    private static boolean generateImage(String strImage, String imgFilePath) {
        // 图像数据为空
        if (strImage == null) {
            return false;
        }
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            // Base64解码
            byte[] bytes = decoder.decodeBuffer(strImage);
            for (int i = 0; i < bytes.length; ++i) {
                if (bytes[i] < 0) {
                    bytes[i] += 256;
                }
            }
            // 生成jpeg图片
            OutputStream out = new FileOutputStream(imgFilePath);
            out.write(bytes);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

}
